home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / RTrace-1.0-src / triangle.c < prev   
Text File  |  1992-08-17  |  7KB  |  174 lines

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *
  11.  * Redistribution and use in source and binary forms are permitted
  12.  * provided that the above copyright notice and this paragraph are
  13.  * duplicated in all such forms and that any documentation,
  14.  * advertising materials, and other materials related to such
  15.  * distribution and use acknowledge that the software was developed
  16.  * by Antonio Costa, at INESC-Norte. The name of the author and
  17.  * INESC-Norte may not be used to endorse or promote products derived
  18.  * from this software without specific prior written permission.
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  */
  23. #include "defs.h"
  24. #include "extern.h"
  25.  
  26. /**********************************************************************
  27.  *    RAY TRACING - Triangle - Version 7.0                            *
  28.  *                                                                    *
  29.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  30.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  31.  *    MODIFIED BY: Antonio Costa, INESC-Norte, December 1991          *
  32.  **********************************************************************/
  33.  
  34. /***** Triangle *****/
  35. real
  36. triangle_intersect(position, vector, object)
  37.   xyz_ptr         position, vector;
  38.   object_ptr      object;
  39. {
  40.   REG real        distance, k, k0;
  41.   xyz_struct      p;
  42.   triangle_ptr    triangle;
  43.  
  44.   REALINC(triangle_tests);
  45.   triangle = (triangle_ptr) object->data;
  46.   k = DOT_PRODUCT(*vector, triangle->transf[2]);
  47.   if (ABS(k) >= ROUNDOFF)
  48.   {
  49.     p.x = triangle->coords[0].x - position->x;
  50.     p.y = triangle->coords[0].y - position->y;
  51.     p.z = triangle->coords[0].z - position->z;
  52.     distance = DOT_PRODUCT(p, triangle->transf[2]) / k;
  53.     if (distance > threshold_distance)
  54.     {
  55.       p.x = distance * vector->x + position->x - triangle->coords[0].x;
  56.       p.y = distance * vector->y + position->y - triangle->coords[0].y;
  57.       p.z = distance * vector->z + position->z - triangle->coords[0].z;
  58.       k = DOT_PRODUCT(p, triangle->transf[0]);
  59.       k0 = DOT_PRODUCT(p, triangle->transf[1]);
  60.       if ((k >= 0.0) AND(k0 >= 0.0) AND(k + k0 <= 1.0))
  61.       {
  62.         triangle->u_hit = k;
  63.         triangle->v_hit = k0;
  64.         return distance;
  65.       }
  66.       return 0.0;
  67.     }
  68.     return 0.0;
  69.   }
  70.   return 0.0;
  71. }
  72. void
  73. triangle_normal(position, object, normal)
  74.   xyz_ptr         position;
  75.   object_ptr      object;
  76.   xyz_ptr         normal;
  77. {
  78.   REG real        t, u, v;
  79.   triangle_ptr    triangle;
  80.  
  81.   triangle = (triangle_ptr) object->data;
  82.   u = triangle->u_hit;
  83.   v = triangle->v_hit;
  84.   t = 1.0 - u - v;
  85.   normal->x = t * triangle->normal[0].x + u * triangle->normal[1].x +
  86.     v * triangle->normal[2].x;
  87.   normal->y = t * triangle->normal[0].y + u * triangle->normal[1].y +
  88.     v * triangle->normal[2].y;
  89.   normal->z = t * triangle->normal[0].z + u * triangle->normal[1].z +
  90.     v * triangle->normal[2].z;
  91.   NORMALIZE(*normal);
  92. }
  93. static void
  94. load_triangle(triangle)
  95.   triangle_ptr    triangle;
  96. {
  97.   int             i;
  98.   REG real        k;
  99.   xyz_struct      temp[3];
  100.  
  101.   NORMALIZE(triangle->normal[0]);
  102.   NORMALIZE(triangle->normal[1]);
  103.   NORMALIZE(triangle->normal[2]);
  104.   temp[0].x = triangle->coords[1].x - triangle->coords[0].x;
  105.   temp[0].y = triangle->coords[1].y - triangle->coords[0].y;
  106.   temp[0].z = triangle->coords[1].z - triangle->coords[0].z;
  107.   temp[1].x = triangle->coords[2].x - triangle->coords[0].x;
  108.   temp[1].y = triangle->coords[2].y - triangle->coords[0].y;
  109.   temp[1].z = triangle->coords[2].z - triangle->coords[0].z;
  110.   CROSS_PRODUCT(temp[2], temp[0], temp[1]);
  111.   NORMALIZE(temp[2]);
  112.   k = 1.0 /
  113.     (temp[0].x * temp[1].y * temp[2].z + temp[0].y * temp[1].z * temp[2].x +
  114.      temp[0].z * temp[1].x * temp[2].y - temp[0].z * temp[1].y * temp[2].x -
  115.      temp[0].x * temp[1].z * temp[2].y - temp[0].y * temp[1].x * temp[2].z);
  116.   triangle->transf[0].x = (temp[1].y * temp[2].z - temp[1].z * temp[2].y);
  117.   triangle->transf[1].x = -(temp[0].y * temp[2].z - temp[0].z * temp[2].y);
  118.   triangle->transf[2].x = (temp[0].y * temp[1].z - temp[0].z * temp[1].y);
  119.   triangle->transf[0].y = -(temp[1].x * temp[2].z - temp[1].z * temp[2].x);
  120.   triangle->transf[1].y = (temp[0].x * temp[2].z - temp[0].z * temp[2].x);
  121.   triangle->transf[2].y = -(temp[0].x * temp[1].z - temp[0].z * temp[1].x);
  122.   triangle->transf[0].z = (temp[1].x * temp[2].y - temp[1].y * temp[2].x);
  123.   triangle->transf[1].z = -(temp[0].x * temp[2].y - temp[0].y * temp[2].x);
  124.   triangle->transf[2].z = (temp[0].x * temp[1].y - temp[0].y * temp[1].x);
  125.   for (i = 0; i < 3; POSINC(i))
  126.   {
  127.     triangle->transf[i].x *= k;
  128.     triangle->transf[i].y *= k;
  129.     triangle->transf[i].z *= k;
  130.   }
  131. }
  132. void
  133. triangle_enclose(object)
  134.   object_ptr      object;
  135. {
  136.   REG int         i;
  137.   xyz_struct      temp1, temp2;
  138.   triangle_ptr    triangle;
  139.  
  140.   triangle = (triangle_ptr) object->data;
  141.   if (object->transf != NULL)
  142.   {
  143.     for (i = 0; i < 3; POSINC(i))
  144.     {
  145.       transform(object->inv_transf, &(triangle->coords[i]), &temp1);
  146.       transform_vector(object->inv_transf, &(triangle->coords[i]),
  147.                        &(triangle->normal[i]), &temp1, &temp2);
  148.       STRUCT_ASSIGN(triangle->coords[i], temp1);
  149.       STRUCT_ASSIGN(triangle->normal[i], temp2);
  150.     }
  151.     FREE(object->transf);
  152.     object->transf = NULL;
  153.   }
  154.   load_triangle(triangle);
  155.   STRUCT_ASSIGN(*(object->min), triangle->coords[0]);
  156.   STRUCT_ASSIGN(*(object->max), triangle->coords[0]);
  157.   for (i = 1; i < 3; POSINC(i))
  158.   {
  159.     object->max->x = MAX(object->max->x, triangle->coords[i].x);
  160.     object->max->y = MAX(object->max->y, triangle->coords[i].y);
  161.     object->max->z = MAX(object->max->z, triangle->coords[i].z);
  162.     object->min->x = MIN(object->min->x, triangle->coords[i].x);
  163.     object->min->y = MIN(object->min->y, triangle->coords[i].y);
  164.     object->min->z = MIN(object->min->z, triangle->coords[i].z);
  165.   }
  166.   /* Adjust dimensions */
  167.   object->max->x += threshold_distance;
  168.   object->max->y += threshold_distance;
  169.   object->max->z += threshold_distance;
  170.   object->min->x -= threshold_distance;
  171.   object->min->y -= threshold_distance;
  172.   object->min->z -= threshold_distance;
  173. }
  174.